const puppeteer = require('puppeteer');
const cheerio = require('cheerio');
const axios = require('axios');
const Source = require('../models/Source');
const Personnel = require('../models/Personnel');
const Changelog = require('../models/Changelog');
const deepSeekService = require('./deepSeekService');
const tunnel = require('tunnel');

// 从环境变量中获取全局代理设置
const DEFAULT_PROXY_ENABLED = process.env.DEFAULT_PROXY_ENABLED === 'true';
const DEFAULT_PROXY_HOST = process.env.DEFAULT_PROXY_HOST || '';
const DEFAULT_PROXY_PORT = parseInt(process.env.DEFAULT_PROXY_PORT) || 0;

/**
 * 监测所有活跃采集源
 */
exports.monitorAllSources = async () => {
  try {
    const activeSources = await Source.find({ status: 'active' });
    console.log(`开始监测 ${activeSources.length} 个采集源`);
    
    for (const source of activeSources) {
      try {
        await monitorSource(source);
        
        // 更新采集源的最后采集时间和状态
        source.lastCrawled = new Date();
        source.status = 'active';
        source.errorMessage = null;
        await source.save();
      } catch (error) {
        console.error(`监测采集源 ${source.name} 失败:`, error);
        
        // 更新采集源状态为错误
        source.status = 'error';
        source.errorMessage = error.message;
        await source.save();
      }
    }
    
    return { success: true, message: '所有采集源监测完成' };
  } catch (error) {
    console.error('监测所有采集源失败:', error);
    throw error;
  }
};

/**
 * 监测单个采集源
 * @param {Object} source 采集源对象
 */
const monitorSource = async (source) => {
  console.log(`开始监测采集源: ${source.name}`);
  
  // 获取页面内容
  const html = await fetchHtml(source.listUrl, source);
  
  // 解析人员列表
  const personnelList = await parsePersonnelList(html, source);
  
  // 并发处理每个人员信息，并发数限制为5
  const concurrencyLimit = 5;
  const chunks = [];
  
  for (let i = 0; i < personnelList.length; i += concurrencyLimit) {
    const chunk = personnelList.slice(i, i + concurrencyLimit);
    chunks.push(chunk);
  }
  
  for (const chunk of chunks) {
    await Promise.all(
      chunk.map(personnelInfo => processPersonnel(personnelInfo, source))
    );
  }
  
  // 检测移除的人员
  await detectRemovedPersonnel(personnelList, source);
  
  console.log(`采集源 ${source.name} 监测完成，发现 ${personnelList.length} 名人员`);
};

/**
 * 获取HTML内容
 * @param {string} url 要获取的URL
 * @param {Object} source 包含代理设置的采集源
 * @returns {Promise<string>} HTML内容
 */
const fetchHtml = async (url, source) => {
  try {
    // 配置浏览器选项
    const launchOptions = {
      headless: "new",
      args: ['--no-sandbox', '--disable-setuid-sandbox']
    };

    // 确定使用的代理设置
    let useProxy = false;
    let proxyHost = '';
    let proxyPort = 0;

    // 优先使用源特定代理
    if (source && source.proxy && source.proxy.enabled && source.proxy.host && source.proxy.port) {
      useProxy = true;
      proxyHost = source.proxy.host;
      proxyPort = source.proxy.port;
    }
    // 否则使用全局代理
    else if (DEFAULT_PROXY_ENABLED && DEFAULT_PROXY_HOST && DEFAULT_PROXY_PORT) {
      useProxy = true;
      proxyHost = DEFAULT_PROXY_HOST;
      proxyPort = DEFAULT_PROXY_PORT;
    }

    // 如果启用了代理，添加代理设置
    if (useProxy) {
      const proxyUrl = `http://${proxyHost}:${proxyPort}`;
      launchOptions.args.push(`--proxy-server=${proxyUrl}`);
      console.log(`使用代理: ${proxyUrl}`);
    }

    // 使用无头浏览器获取内容，处理动态加载的页面
    const browser = await puppeteer.launch(launchOptions);
    const page = await browser.newPage();
    await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 });
    const html = await page.content();
    await browser.close();
    return html;
  } catch (puppeteerError) {
    console.warn(`Puppeteer获取失败，尝试使用axios: ${puppeteerError.message}`);
    
    // 回退到使用axios直接获取
    try {
      const axiosOptions = {
        headers: {
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
          'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
          'Accept-Language': 'en-US,en;q=0.9'
        },
        timeout: 30000
      };
      
      // 确定使用的代理设置
      let useProxy = false;
      let proxyHost = '';
      let proxyPort = 0;

      // 优先使用源特定代理
      if (source && source.proxy && source.proxy.enabled && source.proxy.host && source.proxy.port) {
        useProxy = true;
        proxyHost = source.proxy.host;
        proxyPort = source.proxy.port;
      }
      // 否则使用全局代理
      else if (DEFAULT_PROXY_ENABLED && DEFAULT_PROXY_HOST && DEFAULT_PROXY_PORT) {
        useProxy = true;
        proxyHost = DEFAULT_PROXY_HOST;
        proxyPort = DEFAULT_PROXY_PORT;
      }

      // 如果启用了代理，使用tunnel创建代理隧道
      if (useProxy) {
        const httpsAgent = tunnel.httpsOverHttp({
          proxy: {
            host: proxyHost,
            port: parseInt(proxyPort)
          }
        });
        
        axiosOptions.httpsAgent = httpsAgent;
        axiosOptions.proxy = false; // 禁用默认代理，使用httpsAgent
        console.log(`使用axios代理隧道: ${proxyHost}:${proxyPort}`);
      }
      
      const response = await axios.get(url, axiosOptions);
      return response.data;
    } catch (axiosError) {
      throw new Error(`获取页面内容失败: ${axiosError.message}`);
    }
  }
};

/**
 * 解析人员列表
 * @param {string} html HTML内容
 * @param {Object} source 采集源对象
 * @returns {Array} 人员列表
 */
const parsePersonnelList = async (html, source) => {
  let personnelList = [];
  let listItemSelector, nameSelector, positionSelector, imageSelector, detailLinkSelector;
  let $ = cheerio.load(html);
  
  try {
    // 使用DeepSeek服务分析页面结构
    const aiAnalysis = await deepSeekService.analyzeWebpage(source.listUrl, source.proxy);
    const selectors = aiAnalysis.selectors;
    
    // 使用AI分析的选择器，如果可用的话
    listItemSelector = selectors?.listItemSelector || source.selectors.listItemSelector || 'a[href*="/Leaders/"], a[href*="/Biographies/"], a[href*="/bio/"], .bio-listing, .bio-card, table tr[valign="top"]';
    nameSelector = selectors?.nameSelector || source.selectors.nameSelector || 'h2, h3, .title, .name, strong';
    positionSelector = selectors?.positionSelector || source.selectors.positionSelector || '.position, .subtitle, p, .duty-title';
    imageSelector = selectors?.imageSelector || source.selectors.imageSelector || 'img[src*="bio"], img[src*="portrait"], .official-photo';
    detailLinkSelector = selectors?.detailLinkSelector || source.selectors.detailLinkSelector || 'a, a[href*="/Biographies/"], a[href*="/bio/"]';
    
    // 更新源的选择器配置（如果有更好的选择器）
    if (selectors && Object.keys(selectors).length > 0) {
      source.selectors = {
        ...source.selectors,
        ...selectors
      };
      await source.save();
      console.log(`更新了采集源 ${source.name} 的选择器配置`);
    }
  } catch (error) {
    console.error(`DeepSeek解析人员列表失败: ${error.message}`);
    console.log('回退到传统解析方法');
    
    // 使用配置的选择器提取列表
    listItemSelector = source.selectors.listItemSelector || 'a[href*="/Leaders/"], a[href*="/Biographies/"], a[href*="/bio/"], .bio-listing, .bio-card, table tr[valign="top"]';
    nameSelector = source.selectors.nameSelector || 'h2, h3, .title, .name, strong';
    positionSelector = source.selectors.positionSelector || '.position, .subtitle, p, .duty-title';
    imageSelector = source.selectors.imageSelector || 'img[src*="bio"], img[src*="portrait"], .official-photo';
    detailLinkSelector = source.selectors.detailLinkSelector || 'a, a[href*="/Biographies/"], a[href*="/bio/"]';
  }
  
  // PACAF特殊处理 - 处理所有可能的详情页链接
  const allBioLinks = $('a[href*="/Biographies/"], a[href*="/bio/"], a[href*="/biography/"]');
  if (allBioLinks.length > 0 && source.listUrl.includes('pacaf.af.mil')) {
    console.log(`在PACAF页面发现 ${allBioLinks.length} 个生物链接`);
    
    allBioLinks.each((i, element) => {
      try {
        const linkElement = $(element);
        const href = linkElement.attr('href');
        
        if (href) {
          // 处理相对URL
          let detailUrl = href;
          if (!detailUrl.startsWith('http')) {
            const baseUrl = new URL(source.listUrl);
            detailUrl = new URL(detailUrl, baseUrl.origin).href;
          }
          
          // 提取链接上下文中的名称和职位
          let name = '';
          let position = '';
          
          // 尝试多种获取名称的方法
          if (linkElement.find('strong').length) {
            name = linkElement.find('strong').text().trim();
          } else if (linkElement.parent().find('strong').length) {
            name = linkElement.parent().find('strong').text().trim();
          } else if (linkElement.closest('tr').find('strong').length) {
            name = linkElement.closest('tr').find('strong').text().trim();
          } else {
            // 尝试从链接文本获取名称
            const linkText = linkElement.text().trim();
            if (linkText && linkText.length > 1) {
              name = linkText;
            } else {
              // 尝试从URL中提取名称
              const urlParts = href.split('/');
              const lastPart = urlParts[urlParts.length - 1].replace(/-/g, ' ').replace('.aspx', '');
              if (lastPart.length > 3) {
                name = lastPart.split(' ').map(word => 
                  word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
                ).join(' ');
              }
            }
          }
          
          // 尝试获取职位
          const posElement = linkElement.closest('tr').find('p').first();
          if (posElement.length) {
            position = posElement.text().trim();
          } else if (linkElement.parent().find('p').length) {
            position = linkElement.parent().find('p').text().trim();
          }
          
          // 尝试从职位文本中提取军衔
          let rank = '';
          if (position) {
            const rankMatches = position.match(/(General|Lieutenant General|Major General|Brigadier General|Colonel|Lieutenant Colonel|Major|Captain|Lieutenant|Chief Master Sergeant|Senior Master Sergeant|Master Sergeant|Technical Sergeant|Staff Sergeant|Senior Airman|Airman First Class|Airman)/i);
            if (rankMatches) {
              rank = rankMatches[0];
            }
          }
          
          // 提取图片URL
          let imageUrl = '';
          const imgElement = linkElement.closest('tr').find('img').first();
          if (imgElement.length) {
            imageUrl = imgElement.attr('src') || '';
            if (imageUrl && !imageUrl.startsWith('http')) {
              const baseUrl = new URL(source.listUrl);
              imageUrl = new URL(imageUrl, baseUrl.origin).href;
            }
          }
          
          // 如果有足够的信息，添加到人员列表
          if (name) {
            const uniqueIdentifier = detailUrl || `${source._id}-${name}-${position}`;
            
            // 查找是否已添加
            const exists = personnelList.some(p => p.uniqueIdentifier === uniqueIdentifier);
            
            if (!exists) {
              personnelList.push({
                name,
                position,
                rank,
                organization: source.organization,
                imageUrl,
                detailUrl,
                sourceId: source._id,
                uniqueIdentifier
              });
            }
          }
        }
      } catch (error) {
        console.error('解析生物链接失败:', error);
      }
    });
  }
  
  // 尝试使用DeepSeek服务直接分析页面内容提取人员列表
  try {
    const pageContent = $.text();
    const pageUrl = source.listUrl;
    
    // 构建用于人员列表分析的提示词
    const peopleExtractionPrompt = `请分析以下来自 ${pageUrl} 的网页内容，提取所有人员信息。对于每个人，提取以下字段（如果存在）：
    1. 姓名/名称
    2. 职位/岗位
    3. 军衔（如果有）
    4. 单位/部门/组织
    5. 详情页URL（如果从HTML中能够提取）
    
    内容：
    ${pageContent.substring(0, 8000)}
    
    将结果以JSON数组格式返回，例如：
    [
      {
        "name": "姓名",
        "position": "职位",
        "rank": "军衔",
        "organization": "单位/部门",
        "detailUrl": "详情页URL"
      },
      ...
    ]
    
    只返回JSON数组，不要包含任何解释或额外文本。如果无法提取某项信息，将其设为空字符串。`;
    
    // 调用DeepSeek分析人员列表
    const aiPeopleResult = await deepSeekService.callDeepSeekApi(peopleExtractionPrompt);
    
    try {
      // 尝试解析AI返回的JSON数组
      const jsonMatch = aiPeopleResult.match(/\[[\s\S]*\]/);
      if (jsonMatch) {
        const aiExtractedPersonnel = JSON.parse(jsonMatch[0]);
        if (Array.isArray(aiExtractedPersonnel) && aiExtractedPersonnel.length > 0) {
          console.log(`DeepSeek成功提取${aiExtractedPersonnel.length}名人员信息`);
          
          // 将AI提取的人员信息与传统方法结合
          for (const person of aiExtractedPersonnel) {
            if (person.name) {
              // 生成唯一标识符
              const detailUrl = person.detailUrl || '';
              const uniqueIdentifier = detailUrl || `${source._id}-${person.name}-${person.position || ''}`;
              
              // 相对URL转绝对URL
              let absoluteDetailUrl = person.detailUrl || '';
              if (absoluteDetailUrl && !absoluteDetailUrl.startsWith('http')) {
                const baseUrl = new URL(source.listUrl);
                absoluteDetailUrl = new URL(absoluteDetailUrl, baseUrl.origin).href;
              }
              
              personnelList.push({
                name: person.name,
                position: person.position || '',
                rank: person.rank || '',
                organization: person.organization || source.organization,
                imageUrl: '',  // 图片需要从HTML中提取
                detailUrl: absoluteDetailUrl,
                sourceId: source._id,
                uniqueIdentifier
              });
            }
          }
        }
      }
    } catch (parseError) {
      console.warn(`解析DeepSeek返回的人员JSON失败: ${parseError.message}`);
    }
  } catch (aiError) {
    console.warn(`使用DeepSeek提取人员列表失败: ${aiError.message}`);
  }
  
  // 如果AI分析未能提取人员或提取不完整，继续使用传统的HTML解析方法
  if (personnelList.length === 0) {
    $(listItemSelector).each((i, element) => {
      try {
        // 提取基本信息
        const itemElement = $(element);
        let name = itemElement.find(nameSelector).first().text().trim();
        let position = itemElement.find(positionSelector).first().text().trim();
        
        // 如果没有找到名称，可能整个元素就是名称
        if (!name) {
          name = itemElement.text().trim();
        }
        
        // 尝试提取军衔和单位信息
        let rank = '';
        let organization = source.organization;
        
        // 从职位文本中尝试提取军衔（常见格式：军衔 + 职位）
        if (position) {
          const rankMatches = position.match(/(General|Lieutenant General|Major General|Brigadier General|Colonel|Lieutenant Colonel|Major|Captain|Lieutenant|Chief Master Sergeant|Senior Master Sergeant|Master Sergeant|Technical Sergeant|Staff Sergeant|Senior Airman|Airman First Class|Airman|大将|中将|少将|上将|大校|上校|中校|少校|上尉|中尉|少尉)/i);
          if (rankMatches) {
            rank = rankMatches[0];
            // 从职位中移除军衔
            position = position.replace(rankMatches[0], '').trim();
          }
        }
        
        // 尝试从其他元素提取组织信息
        const orgElement = itemElement.find('.organization, .department, .unit').first();
        if (orgElement.length) {
          organization = orgElement.text().trim() || organization;
        }
        
        // 提取图片
        let imageUrl = '';
        const imgElement = itemElement.find(imageSelector).first();
        if (imgElement.length) {
          imageUrl = imgElement.attr('src') || '';
          // 处理相对URL
          if (imageUrl && !imageUrl.startsWith('http')) {
            const baseUrl = new URL(source.listUrl);
            imageUrl = new URL(imageUrl, baseUrl.origin).href;
          }
        }
        
        // 提取详情页链接
        let detailUrl = '';
        const linkElement = itemElement.is('a') ? itemElement : itemElement.find(detailLinkSelector).first();
        if (linkElement.length || itemElement.is('a')) {
          detailUrl = (itemElement.is('a') ? itemElement : linkElement).attr('href') || '';
          // 处理相对URL
          if (detailUrl && !detailUrl.startsWith('http')) {
            const baseUrl = new URL(source.listUrl);
            detailUrl = new URL(detailUrl, baseUrl.origin).href;
          }
        }
        
        // 生成唯一标识符
        const uniqueIdentifier = detailUrl || `${source._id}-${name}-${position}`;
        
        // 检查是否已添加此人员
        const exists = personnelList.some(p => p.uniqueIdentifier === uniqueIdentifier);
        
        if (name && !exists) {
          personnelList.push({
            name,
            position,
            rank,
            organization,
            imageUrl,
            detailUrl,
            sourceId: source._id,
            uniqueIdentifier
          });
        }
      } catch (error) {
        console.error('解析人员列表项失败:', error);
      }
    });
  }
  
  console.log(`总共找到 ${personnelList.length} 名人员`);
  return personnelList;
};

/**
 * 处理单个人员信息
 * @param {Object} personnelInfo 人员信息对象
 * @param {Object} source 采集源对象
 */
const processPersonnel = async (personnelInfo, source) => {
  try {
    // 检查人员是否已存在
    const existingPersonnel = await Personnel.findOne({ 
      uniqueIdentifier: personnelInfo.uniqueIdentifier 
    });
    
    // 获取人员详情页内容和快照
    let detailPageContent = null;
    let detailPageSnapshot = null;
    let fullDetails = null;
    
    if (personnelInfo.detailUrl && personnelInfo.detailUrl.trim() !== '') {
      try {
        console.log(`获取人员详情: ${personnelInfo.name} (${personnelInfo.detailUrl})`);
        
        // 使用DeepSeek服务获取详情页内容
        const html = await fetchHtml(personnelInfo.detailUrl, source);
        detailPageContent = html;
        
        // 获取详情页快照（使用puppeteer截图）
        try {
          const browser = await puppeteer.launch({
            headless: "new",
            args: ['--no-sandbox', '--disable-setuid-sandbox']
          });
          const page = await browser.newPage();
          await page.goto(personnelInfo.detailUrl, { waitUntil: 'networkidle2', timeout: 60000 });
          detailPageSnapshot = await page.screenshot({ 
            fullPage: true,
            type: 'jpeg',
            quality: 80
          });
          await browser.close();
        } catch (screenshotError) {
          console.error(`获取详情页快照失败: ${personnelInfo.detailUrl}`, screenshotError);
        }
        
        // 获取详细信息
        fullDetails = await fetchPersonnelDetails(personnelInfo.detailUrl, source.proxy);
        
        // 对于PACAF的特殊处理
        if (source.listUrl.includes('pacaf.af.mil') && fullDetails && fullDetails.structuredInfo) {
          // 增强与PACAF网站相关的字段提取
          const structuredInfo = fullDetails.structuredInfo;
          
          // 如果军衔为空但详情页有，则更新
          if (!personnelInfo.rank && structuredInfo.rank) {
            personnelInfo.rank = structuredInfo.rank;
          }
          
          // 如果组织为空但详情页有，则更新
          if ((!personnelInfo.organization || personnelInfo.organization === source.organization) && 
              structuredInfo.organization) {
            personnelInfo.organization = structuredInfo.organization;
          }
          
          // 如果职位为空但详情页有，则更新
          if (!personnelInfo.position && structuredInfo.currentPosition) {
            personnelInfo.position = structuredInfo.currentPosition;
          }
          
          // 保存详情页的专门信息到fullDetails
          if (!fullDetails.militaryInfo) {
            fullDetails.militaryInfo = {};
          }
          
          // 保存军事特有信息
          if (structuredInfo.deployments) {
            fullDetails.militaryInfo.deployments = structuredInfo.deployments;
          }
          
          if (structuredInfo.flightInfo) {
            fullDetails.militaryInfo.flightInfo = structuredInfo.flightInfo;
          }
          
          if (structuredInfo.awards) {
            fullDetails.militaryInfo.awards = structuredInfo.awards;
          }
          
          if (structuredInfo.effectiveDates) {
            fullDetails.militaryInfo.effectiveDates = structuredInfo.effectiveDates;
          }
          
          // 提取图片URL（如果在列表中没有提取到）
          if (!personnelInfo.imageUrl && fullDetails.structuredInfo.imageUrl) {
            personnelInfo.imageUrl = fullDetails.structuredInfo.imageUrl;
          }
        }
      } catch (error) {
        console.error(`获取人员详情页失败: ${personnelInfo.detailUrl}`, error);
      }
    }
    
    if (!existingPersonnel) {
      // 新人员 - 创建记录
      const newPersonnel = new Personnel({
        ...personnelInfo,
        detailPageContent,
        detailPageSnapshot,
        fullDetails,
        source: {
          name: source.name,
          url: source.listUrl
        }
      });
      
      await newPersonnel.save();
      
      // 记录变更日志
      await createChangelog(newPersonnel._id, source._id, 'new', [], '新检测到的人员');
      console.log(`新增人员: ${newPersonnel.name}`);
    } else {
      // 现有人员 - 检查更新
      const changedFields = [];
      
      // 检查各字段是否有变化
      const fieldsToCheck = ['name', 'position', 'rank', 'organization', 'imageUrl', 'detailUrl'];
      for (const field of fieldsToCheck) {
        if (existingPersonnel[field] !== personnelInfo[field] && personnelInfo[field]) {
          changedFields.push({
            field,
            oldValue: existingPersonnel[field],
            newValue: personnelInfo[field]
          });
          existingPersonnel[field] = personnelInfo[field];
        }
      }
      
      // 如果有详情页内容变化
      if (detailPageContent && existingPersonnel.detailPageContent !== detailPageContent) {
        changedFields.push({
          field: 'detailPageContent',
          oldValue: '(previous HTML content)',
          newValue: '(new HTML content)'
        });
        existingPersonnel.detailPageContent = detailPageContent;
      }
      
      // 如果有详情页快照变化
      if (detailPageSnapshot) {
        changedFields.push({
          field: 'detailPageSnapshot',
          oldValue: '(previous snapshot)',
          newValue: '(new snapshot)'
        });
        existingPersonnel.detailPageSnapshot = detailPageSnapshot;
      }
      
      // 如果有详细信息变化
      if (fullDetails) {
        if (JSON.stringify(existingPersonnel.fullDetails) !== JSON.stringify(fullDetails)) {
          changedFields.push({
            field: 'fullDetails',
            oldValue: existingPersonnel.fullDetails,
            newValue: fullDetails
          });
          existingPersonnel.fullDetails = fullDetails;
        }
      }
      
      // 更新source信息
      if (!existingPersonnel.source || existingPersonnel.source.name !== source.name) {
        changedFields.push({
          field: 'source',
          oldValue: existingPersonnel.source || {},
          newValue: { name: source.name, url: source.listUrl }
        });
        existingPersonnel.source = {
          name: source.name,
          url: source.listUrl
        };
      }
      
      // 如果有变化，更新记录和日志
      if (changedFields.length > 0) {
        existingPersonnel.status = 'changed';
        existingPersonnel.lastUpdated = new Date();
        await existingPersonnel.save();
        
        // 记录变更日志
        await createChangelog(
          existingPersonnel._id, 
          source._id, 
          'updated', 
          changedFields, 
          `人员信息更新: ${changedFields.length} 个字段`
        );
        console.log(`更新人员: ${existingPersonnel.name}, 变更字段: ${changedFields.map(f => f.field).join(', ')}`);
      }
    }
  } catch (error) {
    console.error(`处理人员信息失败: ${personnelInfo.name}`, error);
  }
};

/**
 * 获取人员详细信息
 * @param {string} detailUrl 详情页URL
 * @param {Object} proxyConfig 代理配置
 * @returns {Object} 详细信息
 */
const fetchPersonnelDetails = async (detailUrl, proxyConfig = null) => {
  try {
    // 使用DeepSeek服务获取详情页内容
    const html = await fetchHtml(detailUrl, proxyConfig);
    const $ = cheerio.load(html);
    
    // 针对美国空军页面的特殊处理
    const isAirForceUrl = detailUrl.includes('.af.mil') || detailUrl.includes('airforce');
    
    // 提取传记文本
    let biography = '';
    
    if (isAirForceUrl) {
      // 针对美军页面的提取逻辑
      biography = $('#bio-page article, .article-text, .bio-section, div[itemprop="articleBody"]')
        .first()
        .text()
        .trim();
      
      // 如果没有提取到，尝试其他选择器
      if (!biography) {
        biography = $('.biography, .bio, article, .article, .content')
          .first()
          .text()
          .trim();
      }
    } else {
      // 通用提取逻辑
      biography = $('.biography, .bio, article, .article, .content')
        .first()
        .text()
        .trim();
    }
    
    // 提取所有可能的详细信息(关键字-值对)
    const details = {};
    $('table tr, dl, .info-group').each((i, element) => {
      const key = $(element).find('th, dt, .label').first().text().trim();
      const value = $(element).find('td, dd, .value').first().text().trim();
      if (key && value) {
        details[key] = value;
      }
    });
    
    // 空军页面的特殊处理：尝试提取可能的构建块
    if (isAirForceUrl) {
      // 尝试提取照片URL
      const imgUrl = $('img.bio-photo, img.leader-photo, div.grid-item img, div.bio-photo img').attr('src');
      if (imgUrl) {
        details['photoUrl'] = imgUrl.startsWith('http') ? imgUrl : new URL(imgUrl, new URL(detailUrl).origin).href;
      }
      
      // 尝试提取姓名和军衔
      const nameHeader = $('h1.title, h1.bio-name, h1').first().text().trim();
      if (nameHeader) {
        const rankMatch = nameHeader.match(/(General|Gen\.|Lieutenant General|Lt\. Gen\.|Major General|Maj\. Gen\.|Brigadier General|Brig\. Gen\.|Colonel|Col\.|Lieutenant Colonel|Lt\. Col\.|Major|Maj\.|Captain|Capt\.|Lieutenant|Lt\.|Chief Master Sergeant|CMSgt\.|Senior Master Sergeant|SMSgt\.|Master Sergeant|MSgt\.|Technical Sergeant|TSgt\.|Staff Sergeant|SSgt\.|Senior Airman|SrA|Airman First Class|A1C|Airman)/i);
        
        if (rankMatch) {
          details['rank'] = rankMatch[0];
          const nameWithoutRank = nameHeader.replace(rankMatch[0], '').trim();
          details['name'] = nameWithoutRank;
        } else {
          details['name'] = nameHeader;
        }
      }
      
      // 尝试提取当前职位
      const positionElement = $('div.subtitle, p.duty-title, p.current-position').first();
      if (positionElement.length > 0) {
        details['currentPosition'] = positionElement.text().trim();
      }
    }
    
    // 使用DeepSeek提取更多结构化信息
    let structuredInfo = {};
    try {
      // 确定要使用的提示词
      let prompt;
      
      if (isAirForceUrl) {
        // 使用专门针对美国空军的提示词
        prompt = `请从以下美国空军人员详情页中提取完整详细的结构化信息，特别关注以下字段：
        1. name - 完整姓名，包括军衔前缀（如有）
        2. currentPosition - 当前职位/岗位
        3. rank - 军衔（如General, Colonel等）
        4. organization - 所属部队/单位（如太平洋空军、第七舰队等）
        5. imageUrl - 图片URL（如果在HTML中能找到）
        6. education - 教育背景（数组），特别注意Air War College, Air Command and Staff College等军事教育
        7. career - 职业经历（数组，按时间倒序）
        8. deployments - 战斗部署经历（数组，例如Operation Iraqi Freedom等）
        9. flightInfo - 飞行信息，包括总飞行小时数和飞行机型
        10. awards - 军事奖章和荣誉（数组）
        11. effectiveDates - 任命生效日期（例如"June 2022–present"格式）
        12. summary - 个人简介摘要
        
        详情页内容：
        ${html.substring(0, 10000)}
        
        请以JSON格式返回，确保尽可能提取所有上述信息。如果某些信息不存在，请使用空字符串或空数组。只返回JSON对象，不包含任何其他文本。`;
      } else {
        // 使用通用提示词
        prompt = `请从以下人员详情页中提取完整详细的结构化信息，特别关注以下字段：
        1. name - 姓名/名称
        2. currentPosition - 当前职位/岗位
        3. rank - 军衔/级别（如有）
        4. organization - 所属组织/单位
        5. imageUrl - 图片URL（如果在HTML中能找到）
        6. education - 教育背景（数组）
        7. career - 工作经历/专业经历（数组）
        8. honors - 荣誉/奖项（数组）
        9. expertise - 专业领域/研究方向（数组）
        10. summary - 个人简介摘要
        
        详情页内容：
        ${html.substring(0, 10000)}
        
        请以JSON格式返回提取的信息。如果某些信息不存在，将对应字段设为空字符串或空数组。只返回JSON对象，不要包含任何其他解释或文本。`;
      }
      
      // 调用DeepSeek服务提取结构化信息
      const aiResponse = await deepSeekService.callDeepSeekApi(prompt);
      
      // 尝试解析AI返回的JSON
      try {
        const jsonMatch = aiResponse.match(/\{[\s\S]*\}/);
        if (jsonMatch) {
          structuredInfo = JSON.parse(jsonMatch[0]);
          
          // 如果是美军网站，添加一些额外处理
          if (isAirForceUrl && structuredInfo) {
            // 确保军衔标准化
            if (structuredInfo.rank) {
              // 扩展缩写
              const rankMap = {
                'Gen.': 'General',
                'Lt. Gen.': 'Lieutenant General',
                'Maj. Gen.': 'Major General',
                'Brig. Gen.': 'Brigadier General',
                'Col.': 'Colonel',
                'Lt. Col.': 'Lieutenant Colonel',
                'Maj.': 'Major',
                'Capt.': 'Captain',
                'Lt.': 'Lieutenant',
                'CMSgt.': 'Chief Master Sergeant',
                'SMSgt.': 'Senior Master Sergeant',
                'MSgt.': 'Master Sergeant',
                'TSgt.': 'Technical Sergeant',
                'SSgt.': 'Staff Sergeant',
                'SrA': 'Senior Airman',
                'A1C': 'Airman First Class'
              };
              
              for (const [abbr, full] of Object.entries(rankMap)) {
                if (structuredInfo.rank.includes(abbr)) {
                  structuredInfo.rank = full;
                  break;
                }
              }
            }
            
            // 标准化日期格式
            if (structuredInfo.effectiveDates) {
              const datePattern = /(\w+) (\d{4})/;
              const match = structuredInfo.effectiveDates.match(datePattern);
              if (match) {
                structuredInfo.effectiveDateMonth = match[1];
                structuredInfo.effectiveDateYear = match[2];
              }
            }
            
            // 解析飞行信息
            if (structuredInfo.flightInfo && typeof structuredInfo.flightInfo === 'string') {
              const hourMatch = structuredInfo.flightInfo.match(/(\d+,?\d*) (?:flying )?hours?/i);
              if (hourMatch) {
                structuredInfo.totalFlightHours = hourMatch[1].replace(',', '');
              }
              
              const aircraftMatch = structuredInfo.flightInfo.match(/in the ([\w\-\d\/,\s]+)/i);
              if (aircraftMatch) {
                structuredInfo.aircraftTypes = aircraftMatch[1]
                  .split(/,|\sand\s/)
                  .map(type => type.trim())
                  .filter(type => type);
              }
            }
          }
        }
      } catch (parseError) {
        console.warn(`解析DeepSeek返回的JSON失败: ${parseError.message}`);
      }
    } catch (aiError) {
      console.warn(`使用DeepSeek提取结构化信息失败: ${aiError.message}`);
    }
    
    return {
      biography,
      details,
      structuredInfo,
      fullHtml: html, // 保存完整HTML以备后续分析
      lastFetched: new Date()
    };
  } catch (error) {
    console.error(`获取人员详细信息失败: ${detailUrl}`, error);
    return {
      error: error.message,
      lastFetched: new Date()
    };
  }
};

/**
 * 检测已移除的人员
 * @param {Array} currentPersonnelList 当前人员列表
 * @param {Object} source 采集源对象
 */
const detectRemovedPersonnel = async (currentPersonnelList, source) => {
  try {
    // 获取当前列表中的所有唯一标识符
    const currentIdentifiers = currentPersonnelList.map(p => p.uniqueIdentifier);
    
    // 查找数据库中存在但当前列表中不存在的人员
    const removedPersonnel = await Personnel.find({
      sourceId: source._id,
      status: { $ne: 'inactive' },
      uniqueIdentifier: { $nin: currentIdentifiers }
    });
    
    // 处理已移除的人员
    for (const personnel of removedPersonnel) {
      personnel.status = 'inactive';
      await personnel.save();
      
      // 记录变更日志
      await createChangelog(
        personnel._id, 
        source._id, 
        'removed', 
        [], 
        '人员已从列表中移除'
      );
      console.log(`人员已移除: ${personnel.name}`);
    }
    
    return removedPersonnel.length;
  } catch (error) {
    console.error('检测已移除人员失败:', error);
    return 0;
  }
};

/**
 * 创建变更日志
 * @param {string} personnelId 人员ID
 * @param {string} sourceId 采集源ID
 * @param {string} changeType 变更类型
 * @param {Array} changedFields 变更字段
 * @param {string} details 详细信息
 */
const createChangelog = async (personnelId, sourceId, changeType, changedFields, details) => {
  try {
    const changelog = new Changelog({
      personnelId,
      sourceId,
      changeType,
      changedFields,
      details
    });
    await changelog.save();
    return changelog;
  } catch (error) {
    console.error('创建变更日志失败:', error);
    throw error;
  }
};

/**
 * 手动监测单个采集源
 * @param {string} sourceId 采集源ID
 */
exports.monitorSourceById = async (sourceId) => {
  try {
    const source = await Source.findById(sourceId);
    if (!source) {
      throw new Error('采集源不存在');
    }
    
    await monitorSource(source);
    
    // 更新采集源的最后采集时间和状态
    source.lastCrawled = new Date();
    source.status = 'active';
    source.errorMessage = null;
    await source.save();
    
    return { success: true, message: `采集源 ${source.name} 监测完成` };
  } catch (error) {
    console.error(`手动监测采集源失败:`, error);
    throw error;
  }
}; 